/* hooks */
import { useWebSocket, WebSocketResult } from "@vueuse/core";
/* model */
import { BizWebSocketProps } from "@src/component/business/BizWebSocket"
/* util */
import { getWebSocketUrl } from '@src/component/business/BizWebSocket/util'
import Log from "@src/util/log"
import { isFunction } from "@src/util/type";
import { stringify } from "@src/util/lang/object";

// 重连次数
const retriesNum: number = 3
// 错误后重新🔗初始化时间
const errorReconnectTime: number = 5000

function handlerOnWebsocketMessageResult(ws: WebSocket, event: MessageEvent, props: BizWebSocketProps, send: Function) {
  try {
    
    const result = JSON.parse(event.data)
    
    Log.info(result, handlerOnWebsocketMessageResult.name, handlerOnWebsocketMessageResult.name)
    
    if (result?.data?.ping) {
      
      send(stringify({ 
        pong: result.data.ping 
      }))
      
      return 
    }
    
    return props.onMessage && props.onMessage(ws, result.data)
    
  } catch (error) {
    
    Log.error(error, handlerOnWebsocketMessageResult.name)
    
    return props.onMessage && props.onMessage(ws, event)
  }
}

function useBizWebSocket(props: BizWebSocketProps) {
  
  const websocketUrl = getWebSocketUrl(props.url)
  
  let isInConnectWebsocket = false
  let websocketInstance: WebSocketResult<Record<string, any>> | null = null
  
  // Log.info(websocketUrl, useBizWebSocket.name, useBizWebSocket.name)
  
  const handlerWebSocketOnDisconnected = (ws: WebSocket, event: CloseEvent) => {
    
    // Log.info(event, handlerWebSocketOnDisconnected.name, handlerWebSocketOnDisconnected.name)
    
    if (isFunction(props.onDisconnected)) {
      props.onDisconnected && props.onDisconnected(ws, event)
    }
    
    if (isInConnectWebsocket) return
    
    isInConnectWebsocket = true
    websocketInstance && websocketInstance.close()
    
    setTimeout(() => {
      initWebSocket()
      isInConnectWebsocket = false
    }, errorReconnectTime)
    
  }
  
  function initWebSocket() {
    
    // Log.info(websocketUrl, initWebSocket.name, initWebSocket.name)
    websocketInstance = useWebSocket(websocketUrl, {
      autoReconnect: {
        retries: retriesNum,
        delay: 1000,
        onFailed() {
          // Log.error(`${retriesNum}次退出后无法连接WebSocket`, useBizWebSocket.name)
        }
      },
      onDisconnected: handlerWebSocketOnDisconnected,
      onConnected: props.onConnected,
      onMessage: (ws: WebSocket, event: MessageEvent) => {
        handlerOnWebsocketMessageResult(ws, event, props, send)
        Log.info(event, initWebSocket.name, initWebSocket.name)
      },
      onError: props.onError && props.onError,
    })
    
    const { status, data, send, open, close } = websocketInstance
    
    return {
      status,
      data,
      send,
      open,
      close
    }
    
  }
  
  return {
    initWebSocket
  }
}

export default useBizWebSocket;
